/**
 * Subdivision of Dispacher
 * Handles synchronization related messages
 */
package br.unb.core.dispatcher;

import java.net.SocketException;
import java.net.UnknownHostException;

import br.unb.core.message.Message;
import br.unb.core.synchronism.Synchronism;
import br.unb.core.synchronism.ClientController;
import br.unb.core.synchronism.ServerController;
import br.unb.utils.Resource;

public class SyncDispatcher {

    /** Controls synchronism */
    private ServerController serverController;
    /** Controls synchronism */
    private ClientController clientController;

    //case Message.START_SYNCSERVER:
    /**
     * (Executed on server)
     * waits synchronism from a partner
     * @param ipPort IP of the host that will synchrom with us
     */
    public Message startSyncServer(Synchronism syncModel) {
        int port = syncModel.getPort();
        try {
            if (serverController == null) {
                //Resource.println("First time");
                serverController = new ServerController(port);
            } else {
                //Throws away old model
                if (serverController.getPort() != port) {
                    //Resource.println("Changing the port to listen to");
                    serverController.stopSamples();
                    ServerController.yield();
                    serverController = new ServerController(port);
                } else {
                    //Resource.println("Already listening on desired port");
                    //syncServer.stopSamples();
                    //syncServer.startSamples();
                }
            }

        } catch (SocketException e) {
            e.printStackTrace();
            return new Message(Message.Type.ERROR,
                    Resource.getString("TIMING_SERVER")
                    + syncModel.getServerIp()
                    + Resource.getString("COULD_NOT_OPEN_PORT"));
        } catch (UnknownHostException uhe) {
            return new Message(Message.Type.ERROR,
                    Resource.getString("TIMING_SERVER")
                    + syncModel.getServerIp()
                    + Resource.getString("COULD_RESOLVE_HOST"));
        }
        return new Message(Message.Type.ACK,
                Resource.getString("SYNCSERVER_READY")
                + syncModel.toString());
    }

    //case Message.STOP_SYNCSERVER:
    /**
     * Executed on server
     */
    public Message stopServerSync() {
        if (serverController != null) {
            serverController.stopSamples();
        }
        return new Message(Message.Type.ACK, "SYNCSERVER_STOPPED");
    }

    /************************* Synchronism Client ****************************/
    //case Message.START_SYNCCLIENT:
    /**
     * (Executed on client machine)
     * Syncs a remote host
     * @param Synchronism conttains data of remote host IP and port
     */
    public Message startSyncClient(Synchronism syncModel) throws UnknownHostException {
        try {
            //throws away last instance
            if (clientController != null) {
                clientController.closeConnection();
                clientController.stopSamples();
                ClientController.yield();
            }
            clientController = new ClientController(syncModel);
        } catch (SocketException e) {
            e.printStackTrace();
            return new Message(Message.Type.ERROR,
                    Resource.getString("ERROR_ON_CLIENT")
                    + syncModel.getClientIp()
                    + Resource.getString("OF_TIMING")
                    + Resource.getString("PORT_COULD_NOT_BE_OPENED"));
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return new Message(Message.Type.ERROR,
                    Resource.getString("ERROR_ON_CLIENT")
                    + syncModel.getClientIp()
                    + Resource.getString("OF_TIMING")
                    + Resource.getString("SERVER_ADDRESS_NOT_FOUND"));
        }

        return new Message(Message.Type.ACK,
                Resource.getString("SYNCCLIENT_READY")
                + syncModel.toString());
    }

    //case Message.STOP_SYNCCLIENT:
    /**
     * Executed on client
     */
    public Message stopClientSync() {
        if (clientController != null) {
            clientController.stopSamples();
        }
        return new Message(Message.Type.ACK,
                Resource.getString("SYNCCLIENT_STOPPED"));
    }
}
